<?php
/**
 * Created by PhpStorm.
 * User: DELL-PC
 * Date: 2018/8/2
 * Time: 20:44
 */

namespace J\Schema\Collection;


use J\Schema\IElement;
use J\Schema\IWhere;
use J\Schema\Sprite;
use J\Schema\Syntax;
use J\Exception;
use J\Message;

/**
 * Where语句组装器
 */
class Where implements IWhere
{
    protected static $compare = ['<', '>', '=', '<>', '<=', '>=',
        Syntax::OPERATOR_LIKE,Syntax::OPERATOR_NOT_LIKE,
        Syntax::OPERATOR_IN, Syntax::OPERATOR_NOT_IN,
        Syntax::OPERATOR_NOT_NULL, Syntax::OPERATOR_IS_NULL,
        Syntax::OPERATOR_BETWEEN
    ];

    /**
     * @var ICollection
     */
    protected $poem;

    /**
     * @var Sprite[][]
     */
    protected $conditions = [];

    /**
     * Where constructor.
     * @param ICollection $poem
     */
    public function __construct(ICollection $poem)
    {
        $this->poem = $poem;
    }

    public function getCondition()
    {
        return $this->conditions;
    }

    public function andCondition($data, $index = -1)
    {
        if ($index < 0) $index = count($this->conditions);

        if (isset($this->conditions[$index])) {
            $this->conditions[$index] = array_merge($this->conditions[$index], $this->parse($data));
        } else {
            $this->conditions[$index] = $this->parse($data);
        }
        return $index;
    }

    public function orCondition($data)
    {
        $this->conditions[] = $this->parse($data);
        return $this;
    }

    /**
     * 编译查询数组
     * @param array|string $data
     * @return array
     * @throws Exception
     */
    protected function parse($data)
    {
        if ($data === true) return [true];

        if ($data === false) return [false];

        $ids = $data;
        if ($this->isIdList($ids)) {
            return [$this->poem->elements()
                ->getElement(Syntax::KEY_ID)->getSprite($ids)->mapCompare()];
        }

        $r = [];

        if (is_string($data)) return [new Sprite(null, $data, Syntax::OPERATOR_EXPRESSION)];

        $this->poem->elements()->iterateElements(function (IElement $element, $value) use (&$r) {
            $r[] = $element->getSprite($value)->mapCompare();
        }, $data, function ($name, $value) use (&$r) {
            // 创造 id in 语句 来处理 many 查询的
            $rs = $this->poem->getLinker($name)->getCurd()
                ->setWhere([$name => $value])
                ->setRaw(true)
                ->setElements([$this->poem->getName()])
                ->select();

            // 与运算项为false
            if (empty($rs)) {
                $r = [false];
                return false;
            } else {
                $ids = array_column_unique($rs, strtolower($this->poem->getName()));
                $r[] = $this->poem->elements()
                    ->getElement(Syntax::KEY_ID)->getSprite($ids)->mapCompare();
            }

            return true;
        });

        return $r;
    }

    /**
     * 判断是否为ID列表
     *
     * @param mixed $data
     * @return bool
     * @throws Exception
     */
    protected function isIdList(&$data)
    {
        if ($data === null or $data === Syntax::KEY_ID) {
            if (!isset($_REQUEST[Syntax::KEY_ID]))
                throw new Exception(Message::ID_NOT_INPUT);
            $data = $_REQUEST[Syntax::KEY_ID];
            return true;
        }

        return (is_array($data) and isset($data[Syntax::KEY_ID])) or (convert_id($data));
    }
}